天天看點

基于BeautifulSoup抓取網站内容的實踐(Kanunu8)(1)

最近閑來無事,拿來練練手。

注:

由于網站可能會變動,本代碼不保證後面一直都能用,僅講述抓取的思路;

個人純屬研究使用,請不要應用于商業目的;

使用語言:Python

版本:3.4.3

代碼也比較簡單,直接貼上來:

HttpClient.py

1

2

3

4

5

6

7

8

9

10

11

12

<code># -*- coding: utf-8 -*-</code>

<code>import</code> <code>requests</code>

<code>def</code> <code>make_request(url):</code>

<code>    </code><code>print</code><code>(</code><code>'make_request: '</code><code>, url)</code>

<code>    </code><code>r </code><code>=</code> <code>requests.get(url, timeout</code><code>=</code><code>(</code><code>30</code><code>, </code><code>90</code><code>))</code>

<code>#     if r.status_code == 200:</code>

<code>    </code><code>print</code><code>(</code><code>'content-type: '</code><code>, r.headers[</code><code>'content-type'</code><code>])</code>

<code>    </code><code>print</code><code>(</code><code>'encoding: '</code><code>, r.encoding)</code>

<code>    </code><code>print</code><code>(</code><code>'apparent_encoding: '</code><code>, r.apparent_encoding)</code>

<code>    </code><code>return</code> <code>r</code>

Kanunu8.py

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

<code>import</code> <code>os</code>

<code>import</code> <code>sys</code>

<code>import</code> <code>re</code>

<code>import</code> <code>encodings</code>

<code>#為了引用與父目錄同級檔案夾中的方法</code>

<code>sys.path.append(</code><code>".."</code><code>)</code>

<code># 解決gb2312亂碼問題</code>

<code>encodings.aliases.aliases[</code><code>'gb2312'</code><code>] </code><code>=</code> <code>'gb18030'</code>

<code>from</code> <code>bs4 </code><code>import</code> <code>BeautifulSoup</code>

<code>from</code> <code>_pyio </code><code>import</code> <code>open</code>

<code>from</code> <code>util </code><code>import</code> <code>*</code>

<code>book_url </code><code>=</code> <code>''</code>

<code>book_name </code><code>=</code> <code>''</code>

<code>#屏蔽掉作者的連結</code>

<code>writer_link_pattern </code><code>=</code> <code>re.</code><code>compile</code><code>(r</code><code>'.*/writer/\d+\.html'</code><code>)</code>

<code>#由于我用的是Windows平台,檔案名中不能包含下列非法字元,需要過濾</code>

<code>window_illegal_file_name_pattern </code><code>=</code> <code>re.</code><code>compile</code><code>(r</code><code>'[\\|/|:|\*|\?|"|&lt;|&gt;|\|]'</code><code>)</code>

<code>    </code> 

<code>def</code> <code>find_tbody(tag):</code>

<code>    </code><code>if</code> <code>tag.name </code><code>=</code><code>=</code> <code>'tbody'</code><code>:</code>

<code>         </code><code>if</code> <code>tag.find(</code><code>'tbody'</code><code>) </code><code>is</code> <code>None</code>  <code>and</code> <code>tag.find(</code><code>'strong'</code><code>).string </code><code>=</code><code>=</code> <code>'正文'</code><code>:</code>

<code>             </code><code>return</code> <code>True</code>

<code>         </code><code>elif</code> <code>'釋出時間'</code> <code>in</code> <code>tag.get_text():</code>

<code>    </code><code>return</code> <code>False</code>

<code>def</code> <code>strong_with_no_href(tag):</code>

<code>    </code><code>return</code> <code>tag.name </code><code>=</code><code>=</code> <code>'strong'</code> <code>and</code> <code>tag.a </code><code>is</code>  <code>None</code> <code>and</code> <code>tag.font </code><code>is</code> <code>not</code> <code>None</code>

<code>def</code> <code>find_title(tag):</code>

<code>    </code><code>if</code> <code>tag.h1 </code><code>is</code> <code>not</code> <code>None</code><code>:</code>

<code>        </code><code>return</code> <code>tag.h1.font.string</code>

<code>    </code><code>elif</code> <code>tag.h2 </code><code>is</code> <code>not</code> <code>None</code><code>:</code>

<code>        </code><code>return</code> <code>tag.h2.font.string</code>

<code>    </code><code>else</code><code>:</code>

<code>       </code><code>return</code> <code>tag.find(strong_with_no_href).font.string</code>

<code>def</code> <code>make_soup(html):</code>

<code>    </code><code>#     , from_encoding='gb18030'</code>

<code>    </code><code>soup </code><code>=</code> <code>BeautifulSoup(html, </code><code>"html.parser"</code><code>)</code>

<code>    </code><code>print</code><code>(</code><code>'original_encoding: '</code><code>, soup.original_encoding, </code><code>', declared_html_encoding: '</code><code>, soup.declared_html_encoding, </code><code>', from_encoding: '</code><code>, soup.from_encoding)</code>

<code>    </code><code>return</code> <code>soup</code>

<code>def</code> <code>get_legal_window_file_name(name):</code>

<code>    </code><code>if</code> <code>name </code><code>is</code> <code>None</code><code>:</code>

<code>        </code><code>return</code> <code>'unknown'</code>

<code>    </code><code>return</code> <code>window_illegal_file_name_pattern.sub('', name)</code>

<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>'__main__'</code><code>: </code>

<code>    </code><code>book_url </code><code>=</code> <code>input</code><code>(</code><code>'請輸入電子書URL:'</code><code>)</code>

<code>    </code><code># 按任意鍵繼續</code>

<code>#     if input('請按任意鍵開始抓取...'):</code>

<code>#         pass</code>

<code>    </code><code>#擷取Html内容</code>

<code>    </code><code>request </code><code>=</code> <code>HttpClient.make_request(book_url)</code>

<code>    </code><code>html </code><code>=</code> <code>request.content</code>

<code>    </code><code>soup </code><code>=</code> <code>make_soup(html)</code>

<code>    </code><code># 爬取書名</code>

<code>    </code><code>book_name </code><code>=</code> <code>soup.find(</code><code>'title'</code><code>).string</code>

<code>    </code><code>path </code><code>=</code> <code>'./'</code> <code>+</code> <code>get_legal_window_file_name(book_name) </code><code>+</code> <code>'.txt'</code>

<code>    </code><code>links </code><code>=</code> <code>[]</code>

<code>    </code><code>#提取所有章節的連結</code>

<code>    </code><code>for</code> <code>tmp </code><code>in</code> <code>soup.find_all(</code><code>'tbody'</code><code>):</code>

<code>        </code><code>if</code> <code>len</code><code>(tmp.find_all(</code><code>'tr'</code><code>)) &gt; </code><code>1</code> <code>:</code>

<code>            </code><code>all_link </code><code>=</code> <code>tmp.find_all(</code><code>'a'</code><code>)</code>

<code>            </code><code>if</code> <code>not</code> <code>all_link </code><code>is</code> <code>None</code><code>:</code>

<code>                </code><code>links.extend(all_link)</code>

<code>    </code><code>if</code> <code>book_url.endswith(</code><code>'.html'</code><code>):</code>

<code>        </code><code>parent_url </code><code>=</code> <code>book_url[</code><code>0</code><code>:book_url.rindex(</code><code>'/'</code><code>) </code><code>+</code> <code>1</code><code>]</code>

<code>        </code><code>parent_url </code><code>=</code> <code>book_url</code>

<code>    </code><code>with </code><code>open</code><code>(path, </code><code>'w'</code><code>, encoding</code><code>=</code><code>"utf-8"</code><code>) as f:</code>

<code>        </code><code>for</code> <code>link </code><code>in</code> <code>links:</code>

<code>            </code><code># 作家連結,忽略</code>

<code>            </code><code>if</code> <code>not</code> <code>writer_link_pattern.match(link[</code><code>'href'</code><code>]) </code><code>is</code> <code>None</code><code>:</code>

<code>                </code><code>continue</code>

<code>            </code> 

<code>            </code><code>print</code><code>(</code><code>'\n'</code><code>, link.string)</code>

<code>            </code><code>url </code><code>=</code> <code>parent_url </code><code>+</code> <code>link[</code><code>'href'</code><code>]</code>

<code>            </code><code>print</code><code>(url)</code>

<code>            </code><code>response </code><code>=</code> <code>HttpClient.make_request(url)</code>

<code>            </code><code>chapter_soup </code><code>=</code> <code>make_soup(response.content)</code>

<code>            </code><code>chapter_name </code><code>=</code> <code>find_title(chapter_soup)</code>

<code>            </code><code># 章節标題</code>

<code>            </code><code>f.write(</code><code>'\n\n'</code><code>)</code>

<code>            </code><code>f.write(chapter_name)</code>

<code>            </code><code># 章節内容</code>

<code>            </code><code>f.write(chapter_soup.find(</code><code>'p'</code><code>).get_text().replace(</code><code>'&lt;br/&gt;'</code><code>, ''))</code>

<code>#             for p in chapter_soup.find('p').contents:</code>

<code>#                 if p == '&lt;br&gt;':</code>

<code>#                     f.write('\n')</code>

<code>#                 elif p is NavigableString:</code>

<code>#                     f.write(p)</code>

<code>#                 elif p is Tag:</code>

<code>#                     f.write(p.string)</code>

<code>        </code> 

<code>        </code><code>f.flush()</code>

<code>        </code><code>print</code><code>(</code><code>'電子書已成功儲存: '</code><code>, path)</code>

遇到的問題:

不同的書(甚至章節)标題内容、字型(h1,h2...)、标簽結構都不同;

應該是為了增加爬取的難度吧,不過隻能針對遇到的問題進行分析、解決;

本文轉自 breezy_yuan 51CTO部落格,原文連結:http://blog.51cto.com/lbrant/1688440,如需轉載請自行聯系原作者

繼續閱讀