2024-08-13

以下是一个简化的Java爬虫代码示例,用于获取LOL英雄数据和图片,并保存到本地。




import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
 
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
 
public class LeagueOfLegendsCrawler {
 
    private static final String HERO_INFO_URL = "http://lol.esportsentertainment.com/champion/";
    private static final String IMAGE_URL_PREFIX = "http://ddragon.leagueoflegends.com/cdn/9.2.1/img/champion/";
    private static final String SAVE_DIR = "LOLEngines";
 
    public static void main(String[] args) {
        for (int i = 1; i <= 118; i++) { // 假设我们只爬取前118个英雄,实际可以根据实际网站结构爬取所有
            String heroId = String.valueOf(i);
            String heroUrl = HERO_INFO_URL + heroId;
            String imageUrl = IMAGE_URL_PREFIX + heroId + ".png";
            downloadHeroData(heroUrl, imageUrl, heroId);
        }
    }
 
    private static void downloadHeroData(String heroUrl, String imageUrl, String heroId) {
        try {
            Document doc = Jsoup.connect(heroUrl).get();
            Elements nameElements = doc.select("title");
            String heroName = nameElements.get(0).text().replace(" - League of Legends Esports & Entertainment", "");
 
            // 下载图片
            Path imageSavePath = downloadImage(imageUrl, heroName);
 
            System.out.println("Hero Name: " + heroName);
            System.out.println("Image Saved at: " + imageSavePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    private static Path downloadImage(String imageUrl, String fileName) {
        try {
            File tempFile = new File(SAVE_DIR + File.separator + fileName + ".png");
            Path path = Paths.get(tempFile.getAbsolutePath());
            if (tempFile.exists()) {
                System.out.println("File already exists: " + path);
                return path;
            }
 
            URL url = new URL(imageUrl);
            Files.copy(url.openStream(), path);
            return path;
        } catch (IOException e) {
            e.printStackTrace();
        }
        retur
2024-08-13



import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
 
class MySpider(scrapy.Spider):
    name = 'my_spider'
    start_urls = ['http://example.com']
 
    def parse(self, response):
        # 解析响应数据,提取items或requests
        pass
 
# 启动分布式爬虫
process = CrawlerProcess(get_project_settings())
process.crawl('my_spider')
process.start()

这段代码定义了一个简单的Scrapy爬虫,并展示了如何在本地启动一个分布式爬虫进程。这个例子简单明了,并且是编写分布式爬虫的基础。在实际的分布式爬虫项目中,解析函数会更加复杂,并且会涉及到更多的Scrapy组件,如中间件、Item Pipeline等。

2024-08-13

为了回答这个问题,我们需要使用Python的一个库:asyncio。asyncio是Python的标准库,用于编写异步程序。异步程序在一些关键点上会挂起执行,让其他的协程有机会运行。

首先,我们需要一个库来帮助我们下载网页,这个库叫requests。

下面是一个简单的示例,使用asyncio和requests库来异步下载网页:




import asyncio
import requests
 
async def fetch_html(url):
    async with requests.get(url) as response:
        return response.text
 
urls = ['http://example.com/{}'.format(i) for i in range(20)]
 
loop = asyncio.get_event_loop()
htmls = loop.run_until_complete(asyncio.gather(*(fetch_html(url) for url in urls)))
 
for html in htmls:
    print(html)

然而,这个例子只能在网页的数量不太多的时候使用,因为如果网页数量太多,会有一个问题就是会有很多的网络请求,可能会让服务器认为你是一个爬虫而封你的IP。

为了解决这个问题,我们可以使用asyncio.Semaphore来限制同时进行的网络请求的数量。




import asyncio
import requests
 
async def fetch_html(url):
    async with requests.get(url) as response:
        return response.text
 
async def limited_fetch_html(sem, url):
    async with sem:
        return await fetch_html(url)
 
sem = asyncio.Semaphore(5)  # 最多同时进行5个网络请求
urls = ['http://example.com/{}'.format(i) for i in range(20)]
 
loop = asyncio.get_event_loop()
htmls = loop.run_until_complete(asyncio.gather(*(limited_fetch_html(sem, url) for url in urls)))
 
for html in htmls:
    print(html)

这样,我们就可以在不被服务器封禁IP的情况下,高效率的下载多个网页。

然而,上述代码只能应对简单的情况,如果网页中含有js动态加载的内容,上述方法就不能获取到完整的内容。这个时候,我们可以使用webdriver来驱动浏览器,然后用phantomjs作为无头浏览器。




from selenium import webdriver
 
driver = webdriver.PhantomJS()
driver.get('http://example.com')
html = driver.page_source
print(html)
driver.quit()

然而,webdriver是同步的,如果我们想要异步下载多个网页,我们可以把webdriver封装在一个异步函数中。




import asyncio
from selenium import webdriver
 
async def fetch_html(url):
    driver = webdriver.PhantomJS()
    driver.get(url)
    html = driver.page_source
    driver.quit()
    return html
 
urls = ['http://example.com/{}'.format(i) for i in range(20)]
 
loop = asyncio.get_event_loop()
htmls = loop.run_until_complete(asyncio.gather(*(fetch_html(url) for url in urls)))
 
for html in htmls:
    print(html)

然而,上述代码在多个协程同时运行时,可能会出现webdriver启动不起来的问题,因为phantomjs不支持多个进程同时启动。

为了解决这个问题,我们可以使用一个单例模式的webdriver。




import asyncio
from selenium import webdriver
 
class SinglePhantom:
2024-08-13



import weibo
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
 
# 设置微博客户端
client = weibo.APIClient('app_key', 'app_secret', 'access_token', 'access_token_secret')
 
# 获取微博热搜索
def get_weibo_hot_search(timespan):
    hot_search = []
    for i in range(timespan):
        try:
            hot = client.trends.hot(i)
            hot_search.append(hot)
        except Exception as e:
            print(e)
            break
    return hot_search
 
# 解析微博热搜索数据
def parse_weibo_hot_search(hot_search):
    data = []
    for day in hot_search:
        for item in day:
            data.append({
                'date': item['created_at'],
                'rank': item['rank'],
                'keyword': item['keyword'],
                'query': item['query'],
                'type': item['type']
            })
    return data
 
# 数据可视化
def visualize_data(data):
    df = pd.DataFrame(data)
    df = df[df['type'] == '100']  # 只考虑搜索类型为100的数据
    df = df.sort_values(by=['date', 'rank'])
    df_grouped = df.groupby('date')
    
    dates = df_grouped.size().index
    counts = df_grouped.size()
    
    plt.figure(figsize=(15, 6))
    plt.plot(dates, counts, color='blue', marker='o')
    plt.title('微博热搜索趋势', fontsize=16)
    plt.xlabel('日期', fontsize=14)
    plt.ylabel('搜索次数', fontsize=14)
    plt.xticks(rotation=45)
    plt.show()
 
# 执行函数
if __name__ == '__main__':
    timespan = 7  # 获取过去7天的数据
    hot_search = get_weibo_hot_search(timespan)
    data = parse_weibo_hot_search(hot_search)
    visualize_data(data)

这段代码首先设置了微博客户端,然后定义了获取微博热搜索数据的函数,并解析了数据。最后,定义了一个可视化数据的函数,并在主程序中调用这些函数以执行微博热搜索数据的获取和可视化。这个例子展示了如何使用Python进行微博数据的爬取和可视化分析,对于学习微博数据分析的开发者有很好的教育价值。

2024-08-13

WebMagic是一个无依赖的爬虫框架,它提供简单的API,使得在Java语言下编写爬虫非常方便。以下是一个使用WebMagic框架的简单示例,展示如何实现一个简单的网页爬取。

首先,添加WebMagic的依赖到你的项目中。如果你使用Maven,可以添加如下依赖:




<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-core</artifactId>
    <version>0.7.3</version>
</dependency>
<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-extension</artifactId>
    <version>0.7.3</version>
</dependency>

然后,创建一个简单的爬虫类:




import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
 
public class MyPageProcessor implements PageProcessor {
 
    private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
 
    @Override
    public void process(Page page) {
        // 提取页面信息,例如页面的标题和链接
        page.putField("title", page.getHtml().xpath("//h1[@class='title']/text()").toString());
        page.putField("url", page.getUrl().toString());
 
        // 抓取下一页的链接
        page.addTargetRequests(page.getHtml().xpath("//a[@class='next_page']/@href").all());
    }
 
    @Override
    public Site getSite() {
        return site;
    }
 
    public static void main(String[] args) {
        Spider.create(new MyPageProcessor()).addUrl("http://example.com/").thread(5).run();
    }
}

这个类实现了PageProcessor接口,包含了页面处理逻辑和爬虫配置。process方法中使用XPath解析页面,并存储标题和URL。main方法中使用Spider.create()来启动爬虫,并设置了线程数为5。

这个简单的例子展示了如何使用WebMagic来编写一个简单的网页爬取程序。实际应用中,你可能需要根据目标网站的结构调整XPath表达式,以及添加更复杂的处理逻辑。

2024-08-13



import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
 
# 初始化一些变量
job_descriptions = []
job_titles = []
jobs = []
 
# 定义一个函数来获取招聘信息
def get_job_info(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    jobs_on_page = soup.find_all('div', class_='job-card-container')
    for job in jobs_on_page:
        job_title = job.find('h2', class_='title').text
        job_description = job.find('div', class_='description').text
        job_descriptions.append(job_description)
        job_titles.append(job_title)
        jobs.append({'title': job_title, 'description': job_description})
 
# 获取招聘信息
get_job_info('https://www.seek.com.au/jobs/in-all-jobs?page=1')
 
# 将工作描述和标题转换为TF-IDF向量
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(job_descriptions)
cosine_sim = cosine_similarity(tfidf_matrix)
 
# 定义一个函数来获得相似工作的标题
def get_similar_jobs(job_title, cosine_sim):
    idx = job_titles.index(job_title)
    similar_job_indices = cosine_sim[idx].argsort()[::-1][1:6]
    return [jobs[i] for i in similar_job_indices]
 
# 获取与特定工作描述相似的工作
similar_jobs = get_similar_jobs('Data Scientist', cosine_sim)
 
# 打印出相似的工作
for job in similar_jobs:
    print(job['title'])

这个简化的代码实例展示了如何使用Python爬取招聘信息,并使用TF-IDF和cosine相似性来找出相似的工作描述。这个系统可以作为一个基础来进行工作相关性的研究和推荐。

2024-08-13

Selenium被检测为爬虫的问题可能是由于它的默认设置或者特定网站的反爬机制触发的。以下是一些常见的绕过和屏蔽爬虫检测的策略:

  1. 使用代理服务器:可以设置Selenium使用代理服务器,这样可以改变你的IP地址。
  2. 使用不同的浏览器引擎:例如,使用PhantomJS(现在已经不再维护)或者Chrome/Firefox的无头模式。
  3. 设置合适的浏览器标识:使用user-agent在请求中伪装成常见的浏览器。
  4. 使用自动化延时:增加每个请求之间的延时,模仿人的行为。
  5. 使用JavaScript来操作页面:通过Selenium直接执行JavaScript代码来模拟正常用户的行为。
  6. 使用headless模式:如果使用的是Chrome或Firefox,可以启用headless模式。
  7. 使用VPN:更换IP地址,确保你的IP不会被网站记录或者标记为爬虫。
  8. 关闭图片和CSS加载:减少加载内容,减少被检测为爬虫的可能性。

下面是一个简单的示例代码,使用Selenium和Chrome浏览器在无头模式下运行,并设置了合适的用户代理:




from selenium import webdriver
from selenium.webdriver.chrome.options import Options
 
# 初始化Chrome选项
chrome_options = Options()
chrome_options.add_argument("--headless")  # 无头模式
chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")  # 设置用户代理
 
# 启动Chrome浏览器
driver = webdriver.Chrome(options=chrome_options)
 
# 打开页面
driver.get("http://example.com")
 
# ... 进行其他操作 ...
 
# 关闭浏览器
driver.quit()

请根据实际情况选择适合的绕过策略,并适当调整代码以适应你的需求。

2024-08-13



import scrapy
 
class DoubanMovieItem(scrapy.Item):
    # 定义爬取的字段
    movie_name = scrapy.Field()
    movie_rating = scrapy.Field()
    movie_comment = scrapy.Field()
 
class DoubanMovieSpider(scrapy.Spider):
    name = 'douban_movie'
    allowed_domains = ['douban.com']
    start_urls = ['https://movie.douban.com/top250']
 
    def parse(self, response):
        # 提取电影信息的xpath路径
        movie_selectors = response.xpath('//div[@class="info"]')
        for movie_selector in movie_selectors:
            item = DoubanMovieItem()
            # 提取电影名称
            movie_name = movie_selector.xpath('.//a/span[1]/text()').extract_first()
            item['movie_name'] = movie_name.strip() if movie_name else None
            # 提取电影评分
            movie_rating = movie_selector.xpath('.//div[@class="star"]/span[2]/text()').extract_first()
            item['movie_rating'] = movie_rating.strip() if movie_rating else None
            # 提取电影评论
            movie_comment = movie_selector.xpath('.//p[@class="quote"]/span/text()').extract_first()
            item['movie_comment'] = movie_comment.strip() if movie_comment else None
            yield item
 
        # 提取下一页链接并进行爬取
        next_page_url = response.xpath('//span[@class="next"]/a/@href').extract_first
        if next_page_url:
            next_page_full_url = response.urljoin(next_page_url)
            yield scrapy.Request(next_page_full_url, callback=self.parse)

这段代码实现了一个简单的Scrapy爬虫,用于抓取豆瓣电影TOP250的电影名称、评分和评论。它使用XPath选择器来定位页面元素,并使用Item对象来存储爬取的数据。此外,它还实现了简单的分页逻辑来爬取所有页的数据。

2024-08-13



import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from statsmodels.tsa.arima_model import ARIMA
from fbprophet import Prophet
 
# 假设我们有以下函数来获取智慧交通数据
def get_data(city, date):
    # 这里应该是获取数据的代码,但由于数据不公开,我们模拟一些数据返回
    return pd.DataFrame({
        'time': pd.date_range(start=date, periods=24*7, freq='H'),
        'car_count': np.random.randint(1000, 10000, size=24*7)
    })
 
# 获取数据
city = '北京'
date = '2021-01-01'
data = get_data(city, date)
 
# 数据预处理
data['hour'] = data['time'].dt.hour
data = data.set_index('time')
 
# 使用fbprophet进行时间序列预测
model = Prophet(daily_seasonality=True, weekly_seasonality=True)
model.fit(data)
future = model.make_future_dataframe(periods=24*7)
forecast = model.predict(future)
 
# 画出预测图
fig1 = model.plot(forecast)
 
# 保存图表
fig1.savefig(f'prophet_prediction_{city}.png')
 
# 输出预测结果
print(forecast[['ds', 'yhat']])

这个示例展示了如何使用Prophet模型进行时间序列预测,并将预测结果保存为图片文件。注意,这里的数据是模拟的,实际应用中需要替换为实际的交通数据。

2024-08-13



import requests
from bs4 import BeautifulSoup
import pandas as pd
 
# 设置请求头,模拟浏览器访问
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
 
def get_data(url):
    response = requests.get(url, headers=headers)
    soup = BeautifulSoup(response.text, 'lxml')
    data = soup.find_all('div', class_='title')
    rank = [i.span.get_text() for i in soup.find_all('div', class_='num')]
    names = [i.a.get_text() for i in data]
    hrefs = ['https://www.toutiao.com' + i.a.get('href') for i in data]
    return rank, names, hrefs
 
def main(url):
    rank, names, hrefs = get_data(url)
    data = pd.DataFrame(list(zip(rank, names, hrefs)), columns=['排名', '名称', '链接'])
    print(data)
    data.to_csv('今日头条热榜.csv', index=False, encoding='utf-8')
 
if __name__ == '__main__':
    url = 'https://www.toutiao.com/hotwords/'
    main(url)

这段代码首先定义了请求头,用于模拟浏览器访问网页。get_data 函数用于获取网页数据,并通过BeautifulSoup进行解析。main 函数则是程序的主要逻辑,它调用get_data函数获取数据,并将数据存储在一个DataFrame中,最后将数据保存到CSV文件中。最后,在__name____main__时,执行主函数,开始爬取数据。